AddCSLuaFile( "shared.lua" )
AddCSLuaFile( "cl_init.lua" )
AddCSLuaFile("cl_scroll.lua")
 
include( 'shared.lua' )


PropFight = {
	GM = GM
}

function PropFight.playerCleanup(ply)
	if ply.props != nil then
		for k,v in pairs(ply.props) do
			v:Remove()
		end
	end
	ply.props = {} 
end
playerCleanup = PropFight.playerCleanup

function PropFight.bodyCleanup(ply)
	if ply.bodys != nil then
		for k,v in pairs(ply.bodys) do
			v:Remove()
		end
	end
	ply.bodys = {} 
end
bodyCleanup = PropFight.bodyCleanup


function PropFight.babyGod(ply)
	ply:SetCollisionGroup(COLLISION_GROUP_WORLD)
	ply:SetColor(0, 255, 0, 155)

	ply.isBabyGod = true

	timer.Create(ply:UniqueID().."_babygod", 5, 1, unBabyGod, ply)

end
babyGod = PropFight.babyGod

function PropFight.cancelBabyGod(ply)
	timer.Stop(ply:UniqueID().."_babygod")
	ply.isBabyGod = false
end
cancelBabyGod = PropFight.cancelBabyGod


function PropFight.unBabyGod(ply)

	ply.isBabyGod = false
	ply:Give( "weapon_propgun" )
	ply:SetCollisionGroup(COLLISION_GROUP_PLAYER)
	ply:SetHealth(1000)   
	ply:SetWalkSpeed(260) 
	ply:SetRunSpeed (340) 
	ply:SetColor(255, 255, 255, 255)
end
unBabyGod = PropFight.unBabyGod

function GM:PlayerInitialSpawn(ply)
	ply:KillSilent()
	ply:SetTeam(3)
	ply:Spectate( OBS_MODE_CHASE )
	ply:ConCommand("team_menu")	
	
	ply.bodys = {}
end

function GM:PlayerSpawn( ply )
	if (ply:Team() == 3) then ply:KillSilent() return end
    self.BaseClass:PlayerSpawn( ply )  
	if ply.propData == nil then 
		ply.propData = {}
		ply.propData.prop = "models/Combine_Helicopter/helicopter_bomb01.mdl"
		ply.propData.propRate = models_t[1].rate
		ply.propData.propForce = models_t[1].force
	end
	if(ply.props != nil) then
		playerCleanup(ply)
	end

	babyGod(ply)
	umsg.Start("show_model_panel", ply)	
	umsg.End()	
	
end

function GM:PlayerLoadout(ply)

end

 
function GM:PropBreak(breaker, ent)
	local index = ent.propIndex
 	local owner = ent:GetOwner()
	
	if owner == nil then return end
	if !owner:IsPlayer() then return end
	
	local tbl = owner.props
	
	if tbl[index] == nil then return end
	local derp = table.KeyFromValue(owner.props, ent)
	table.remove(owner.props, derp)
	print(derp .." was KeyFromValue")
	
end

function GM:PlayerShouldTakeDamage( victim, ent )
	pl = ent:GetOwner()
	if !pl:IsPlayer() or !victim:IsPlayer() then return end
	if( pl:Team() == victim:Team() and GetConVarNumber( "mp_friendlyfire" ) == 0 ) then
			return false 
	else
		return true
	end
	 
end
 


function GM:EntityTakeDamage( ent, inflictor, attacker, amount, dmginfo)

	if (ent:IsPlayer()) then	
		if(attacker:GetClass() == "prop_physics") then
			local mdl_i = string.lower(attacker:GetModel())
			local dmg_info = nil
			for k, v in pairs(models_t) do
				if mdl_i ==  string.lower(v.mdl) then
					dmg_info = v.dmg
					break
				end
			end
			dmginfo:ScaleDamage(dmg_info)
			
			if ent:Team() == attacker:GetOwner():Team() then return end
			umsg.Start("hurt_log")
				umsg.Entity(ent)
				umsg.Entity(attacker)
			umsg.End()		
	
			if !ent:IsPlayer() then return end
			local pos = dmginfo:GetDamagePosition()
			local dmg = dmginfo:GetDamage()

			if !ent:IsPlayer() then
				ent = ent:GetOwner()
			end

			umsg.Start("dmgText")
				umsg.Entity(ent)
				umsg.Short(dmg)
				umsg.Vector(pos)
			umsg.End()
			
			--doBleed(ent)
			
		end
	end 
end

/*
function paintDown(start, effname, ignore)
   local btr = util.TraceLine({start=start, endpos=(start + Vector(0,0,-256)), filter=ignore, mask=MASK_SOLID})
   util.Decal(effname, btr.HitPos+btr.HitNormal, btr.HitPos-btr.HitNormal)
end

function doBleed(ent)
   if not IsValid(ent) or (ent:IsPlayer() and (not ent:Alive())) then
      return
   end

   local jitter = VectorRand() * 30
   jitter.z = 20

   util.paintDown(ent:GetPos() + jitter, "Blood", ent)
end
*/

function GM:PlayerDisconnected(ply)
	bodyCleanup(ply)
	playerCleanup(ply)
	ply.props = {}
	ply.bodys = {}
end


--START
function PropFight.endRound(winner)
	umsg.Start( "winner_msg")
		umsg.Short(winner)
	umsg.End()
	
	umsg.Start("hide_model_panel", ent)	
	umsg.End()

	team.SetScore(1, 0)
	team.SetScore(2, 0)

	--reset player scores and remove their props , plox leave :D
	for k,v in pairs(player.GetAll())do
		playerCleanup(v)
		bodyCleanup(v)
		v:StripWeapons()
		if(v:Alive()) then
			v:KillSilent()
		end
		
		if(!v:Alive()) then
			timer.Simple(5, function()
				v:Spawn()
			end)
		end
		v:SetFrags(0)
		v:SetDeaths(0)
	
	end
end
endRound = PropFight.endRound




function scrollDown( ply, command, args )
	if ply.propData == nil then ply.propData = {} end
	if ply.propData.inc == nil then ply.propData.inc = 0 end
	if ply.propData.prop == nil then ply.propData.prop = "models/Combine_Helicopter/helicopter_bomb01.mdl" end

	ply.propData.inc = ply.propData.inc - 1
	if(ply.propData.inc <= 0) then
		ply.propData.inc  = #models_t
	end
	umsg.Start("change_panel_model", ply)
		umsg.Short(ply.propData.inc)
	umsg.End()
	ply.propData.prop = models_t[ply.propData.inc].mdl
	ply.propData.propForce = models_t[ply.propData.inc].force
	ply.propData.propRate = models_t[ply.propData.inc].rate
end     
concommand.Add( "pf_scroll_down", scrollDown )

function scrollUp( ply, command, args )
	if ply.propData == nil then ply.propData = {} end
	if ply.propData.inc == nil then ply.propData.inc = 0 end
	if ply.propData.prop == nil then ply.propData.prop = "models/Combine_Helicopter/helicopter_bomb01.mdl" end
	
	ply.propData.inc = ply.propData.inc + 1

	if(ply.propData.inc > #models_t) then
		ply.propData.inc  = 1
	end
	umsg.Start("change_panel_model", ply)
		umsg.Short(ply.propData.inc)
	umsg.End()
	ply.propData.prop = models_t[ply.propData.inc].mdl
	ply.propData.propForce = models_t[ply.propData.inc].force
	ply.propData.propRate = models_t[ply.propData.inc].rate
	--ply:SetNetworkedString("prop", args[1])

end     
concommand.Add( "pf_scroll_up", scrollUp )


concommand.Add("end_round", function(ply, cmd, args ) 
	if !ply:IsAdmin() then return end 
	endRound(tonumber(args[1]))
end)

function GM:PlayerSelectSpawn( ply ) 
    local red_spawn = ents.FindByClass( "info_player_terrorist" )
    local blue_spawn = ents.FindByClass( "info_player_counterterrorist" )
    local random_red = math.random(#red_spawn)
    local random_blue = math.random(#blue_spawn)
	if(ply:Team() == 1 and GAMEMODE:IsSpawnpointSuitable( ply, red_spawn[random_red], false)) then
		return red_spawn[random_red]
	elseif(ply:Team() == 2 and GAMEMODE:IsSpawnpointSuitable( ply, blue_spawn[random_blue], false)) then
		return blue_spawn[random_blue]
	end	
 
end

function GM:CanPlayerSuicide( ply )
	if ply:IsAdmin() then
		ply:PrintMessage(HUD_PRINTTALK, "You commited suicide!")
		return true
	end
	ply:PrintMessage(HUD_PRINTTALK, "You can't suicide!")
	return false
end


sprays = {}
function GM:PlayerSpray(ply)
    --ply:AllowImmediateDecalPainting() 
	local tr = ply:GetEyeTrace()
	sprays[ply:UniqueID()] = {
		pos = tr.HitPos,
		ang = tr.HitNormal
	}
	
	datastream.StreamToClients( player.GetAll(), "sprays", sprays)
end

function getSprays()
	PrintTable(sprays)
end
concommand.Add("test_spray", getSprays)

function GM:PlayerCanHearPlayersVoice( ply1, ply2 )
	if ply1:Team() != ply2:Team() then
		return false
	end
end

-- function GM:PlayerJoinTeam( ply, teamid )
	-- if team.NumPlayers(1) > team.NumPlayers(2) then
		-- return true
	-- else
		-- return false
	-- end
-- end

local var = CreateConVar( "pf_maxscore", 20, FCVAR_REPLICATED)
local var2 = CreateConVar( "pf_maxprops", 5, FCVAR_REPLICATED)
local var3 = CreateConVar( "pf_ragdoll_time", 120, FCVAR_REPLICATED)
local var3 = CreateConVar( "pf_ragdoll_cleanup", 0, FCVAR_REPLICATED)

if(GetConVar("pf_ragdoll_cleanup"):GetInt() > 0) then
	timer.Create("clean_rags", GetConVar("pf_ragdoll_time"):GetInt(), 0, function()
		for k,v in pairs(ents.FindByClass("prop_ragdoll")) do
			v:Remove()
		end
	end)
end

concommand.Add("pf_maxprops", function(ply, cmd, args )
	if !ply:IsAdmin() then return end 
	if(tonumber(args[1]) != GetConVar("pf_maxprops"):GetInt()) then
		for k,v in pairs(player.GetAll()) do
			playerCleanup(v)
		end
	end
end)

health_kits = {}

function GM:InitPostEntity()
	health_kits = ents.FindByClass("healthkit")
	for k,v in pairs(health_kits) do
		local pos = v:GetPos()
		v:Remove()
		local kit = ents.Create("healthkit")
		kit:SetPos(pos + Vector(0, 0, 10))
		kit:Spawn()
		kit:PhysWake()
	end		
	spawnBall()
	GAMEMODE.SpawnDissolver()
	-- local board = ents.Create("score_board")
	-- board:SetPos(Vector(0, 0, 0))
	-- board:Spawn()
	
	-- timer.Create("health_kits", 30, 0,  function()
		-- for k,v in pairs(health_kits) do
			-- if v != nil then 
				-- local pos = v:GetPos()
				-- v:Remove()
				-- local kit = ents.Create("healthkit")
				-- kit:SetPos(pos + Vector(0, 0, 10))
				-- kit:Spawn()
				-- kit:PhysWake()
			-- end
		-- end	
	-- end)
end

function doHealthKits()
	for k,v in pairs(health_kits) do
		local pos = v:GetPos()
		v:Remove()
		local kit = ents.Create("healthkit")
		kit:SetPos(pos + Vector(0, 0, 10))
		kit:Spawn()
		kit:PhysWake()
		print(v:GetPos().. " pos")
	end	
end
concommand.Add("test_kits", doHealthKits)


require("cmd") 
local updated = false
hook.Add("Think", "FastDLUpdater", function()
        if (updated) then return end
        updated = true
        cmd.exec([[copy "C:\\gmod_build\\orangebox\\garrysmod\\cache\\*" "C:\\nginx\\html\\fastdl\\build\\cache\\"]])
        cmd.exec([[bzip2.exe -z C:\\nginx\\html\\fastdl\\build\\cache\\*.dua]])
        --cmd.exec([[ftp -i -s:D3vineBuild.ftps]])
        --cmd.exec([[del /q ..\\FastDL\\cache\\*]])
end)

function GM:SpawnDissolver()
	DISSOLVER = ents.Create("env_entity_dissolver")
	DISSOLVER:SetPos(Vector(0, 0, 0))
	DISSOLVER:SetKeyValue("magnitute", 0)
	DISSOLVER:SetKeyValue("target", "dissolveme")
	DISSOLVER:SetKeyValue("dissolvetype", 0)
	DISSOLVER:Spawn()
end

function GM:Dissolve()
	DISSOLVER:Fire("Dissolve", "dissolveme")
end

local ent = FindMetaTable("Entity")
function ent:Dissolve()
	self:SetKeyValue("targetname", "dissolveme")
	self:SetCollisionGroup(COLLISION_GROUP_NONE)
	self:GetPhysicsObject():EnableGravity(false)
	self:SetVelocity(self:GetVelocity()*0.04)
	GAMEMODE.Dissolve()
end



--[[ function GM:EntityRemoved(ent)
    if !ent:IsValid() then return end
	local ply = ent:GetOwner()
	if !ply:IsPlayer() then return end
    //if(ent:GetClass() == "healthkit") then
		--table.remove(health_kits, table.KeyFromValue(health_kits, ent))
	table.remove(ply.props, table.KeyFromValue(ent))
	Msg("removed " .. ent:GetModel() .. "!")
	print("Removed "..table.KeyFromValue(ply.props, ent))
	//end
end
 ]]

function blueTeamExit(ent)
	print(ent:GetClass())
	if(ent:GetClass() == "pf_ball") then
		ent:Remove()
		spawnBall()
		return
	end
	if(ent:IsPlayer())then
		if(ent:Team() == 1)then
			ent:Kill()
		end
	end
end


function redTeamExit(ent)
	print(ent:GetClass())
	if(ent:GetClass() == "pf_ball") then
		ent:Remove()
		spawnBall()
		return
	end
	if(ent:IsPlayer())then
		if(ent:Team() == 2)then
			ent:Kill()
		end
	end
end


function spawnBall()
	local ball = ents.Create("pf_ball")
	ball:SetPos(Vector(-102, -769, -178))
	ball:Spawn()
	for k,v in pairs(player.GetAll())do		
		v:ChatPrint("The ball was spawned!")
	end
end
concommand.Add("spawn_ball", spawnBall)

score_model = "models/Gibs/HGIBS.mdl"
prop_class = "pf_ball"
function redTeamScore(ent)
	--print("Class: "..ent:GetClass())
	local ply = ent.owner
	--print("Nick: "..ply:Nick())
	if !ply:IsPlayer() then return end
	if ply:Team() != 1 then return end

	--if string.lower(score_model) != string.lower(ent:GetModel()) then return end
	if string.lower(prop_class) != string.lower(ent:GetClass()) then return end
	for k,v in pairs(player.GetAll())do		
		v:ChatPrint("Red team scored! ("..ply:Nick()..")")
	end
	umsg.Start("ball_holder")
		umsg.Entity(nil)
	umsg.End()
	ent:Dissolve()
	playerAddScore(ply, 1)
	spawnBall()
	--playerCleanUp(ply)
end

function blueTeamScore(ent)
	--print("Class: "..ent:GetClass())
	local ply = ent.owner
	--print("Nick: "..ply:Nick())
	if !ply:IsPlayer() then return end
	if ply:Team() != 2 then return end
	--if string.lower(score_model) != string.lower(ent:GetModel()) then return end

	if string.lower(prop_class) != string.lower(ent:GetClass()) then return end
	for k,v in pairs(player.GetAll())do
		v:ChatPrint("Blue Team scored! ("..ply:Nick()..")")
	end
	umsg.Start("ball_holder")
		umsg.Entity(nil)
	umsg.End()
	ent:Dissolve()
	playerAddScore(ply, 1)
	spawnBall()
	--playerCleanUp(ply)
end

function PropFight.playerAddScore(ply, inc)
	local plyTeam = ply:Team()
	local maxScore = GetConVar("pf_maxscore"):GetInt()
	
	ply:AddFrags(inc)
	team.AddScore(ply:Team(), inc)
	
	if(team.GetScore(plyTeam) >= maxScore) then
		endRound(plyTeam)
	end
end
playerAddScore = PropFight.playerAddScore



function ballDeath(ply)
	if(!ply:HasWeapon("weapon_ball")) then return end
    ply:GetWeapon("weapon_ball"):Remove()
	local bar = ents.Create("pf_ball")
	bar:SetPos(ply:GetPos() + Vector(0,0,24))
	bar:Spawn()
end
concommand.Add("balldeath", ballDeath)

function GM:PlayerDeath( ent, weapon, attacker )
	local sound = "vo/npc/barney/ba_ohshit03.wav"
	util.PrecacheSound(sound)
	ent:EmitSound(sound, 72, 100)
	
	--table.insert(ply.bodys, 

	umsg.Start("hide_model_panel", ent)	
	umsg.End()

	if !ent:IsPlayer() then return end 
	if attacker:GetClass() != "prop_physics" then return end 
	
	local ply = attacker:GetOwner() or attacker
	-- if ply:Team() != ent:Team() then
		-- playerAddScore(ply, 1)
	-- end
	--ent:AddDeaths(1)
	ballDeath(ent)
	sendDeathLog(ent, ply)
	serverSideRagdolls(ent)
	

	timer.Simple(5, function()
		if(!ent:Alive()) then
			ent:Spawn()
		end
	end)

end

function PropFight.sendDeathLog(ent, attacker)
	umsg.Start("death_log")
		umsg.Entity(ent)
		umsg.Entity(attacker)
	umsg.End()	
end
sendDeathLog = PropFight.sendDeathLog

function serverSideRagdolls(ent)
	local ragdoll = ents.Create( "prop_ragdoll" )
	if ragdoll:IsValid() then
		ragdoll:SetModel(ent:GetModel())
		ragdoll:SetKeyValue( "origin", ent:GetPos().x .. " " .. ent:GetPos().y .. " " .. ent:GetPos().z )
		ragdoll:Spawn()
		ragdoll:Activate()
		ragdoll:SetOwner(ent)
		--ragdoll:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
		table.insert(ent.bodys, ragdoll)
		ent:SpectateEntity( ragdoll )
		
		local ragBones = ragdoll:GetPhysicsObjectCount()				
		for i = 1, ragBones - 1 do				
			local ragBone = ragdoll:GetPhysicsObjectNum( i )
			if ValidEntity( ragBone ) then	
				local ragBonePos, ragBoneAng = ent:GetBonePosition( ragdoll:TranslatePhysBoneToBone( i ) ) 
				ragBone:SetPos( ragBonePos )
				ragBone:SetAngle( ragBoneAng )					
				ragBone:SetVelocity( ragdoll:GetVelocity() )					
			end				
		end			
		local crapDoll = ent:GetRagdollEntity()
		crapDoll:Remove()
	end
end
--END



function team_1( ply ) 
	if team.Joinable(1) then 
		cancelBabyGod(ply)
		ply:KillSilent()
		playerCleanup(ply)
		ply:SetTeam( 1 ) 
		ply:Spawn()
		--ply:SetModel("models/Combine_Soldier_PrisonGuard.mdl")
		ply:SetColor(255, 0, 0)
	end
end 

function team_2( ply ) 
	if team.Joinable(2) then 
		cancelBabyGod(ply)
		ply:KillSilent()
		playerCleanup(ply)
		ply:SetTeam( 2 )
		ply:Spawn()
		--ply:SetModel("models/player/ct_urban.mdl")
		ply:SetColor(0, 0, 255)
	end

end 

function team_3( ply ) 

	cancelBabyGod(ply)
	ply:KillSilent()
	playerCleanup(ply)	
	ply:SetTeam( 3 ) 
	ply:Spawn()
	ply:StripWeapons()
	ply:Spectate( OBS_MODE_CHASE )
end 

concommand.Add( "team_1", team_1 ) 
concommand.Add( "team_2", team_2 ) 
concommand.Add( "team_3", team_3 ) 

function teamMenu( ply )
	ply:ConCommand( "team_menu" )
end
hook.Add("ShowHelp", "teamMenu", teamMenu)

function findPlayerByName(name) 
	for k,v in pairs(player.GetAll()) do
		if(string.find(string.lower(v:Nick()), string.lower(name))) then
			return v
			
		end
	end
end

function setTeam(ply, cmd, args)
	local p = findPlayerByName(args[1])
	if !p:IsPlayer() then return end
	print(p:Nick())
	p:StripWeapons()
	p:KillSilent()
	p:SetTeam(args[2])
	p:Spawn()
	
end
concommand.Add("set_team", setTeam)


